"""
Grave! Important! Важно!

Proletoj el ĉiuj landoj, unuiĝu!
Workers of the world, unite!
Пролетарии всех стран, соединяйтесь!

https://tkom.pro
"""

import sys
from django.db import models
from django.db.models import Max
from django.urls import reverse
from django.contrib.auth.models import Permission
from django.utils.translation import gettext_lazy as _
from siriuso.models.postgres import CallableEncoder
from siriuso.utils import default_lingvo, get_enhavo, perms
from main.models import Uzanto
from main.models import SiriusoBazaAbstrakta3, SiriusoBazaAbstraktaKomunumoj, SiriusoBazaAbstraktaUzanto
from main.models import SiriusoKomentoAbstrakta, SpecialajGrupoj
from komunumoj.models import KomunumojAliro, Komunumo, KomunumoMembro
from uzantoj.models import UzantojAliro
from embed_video.fields import EmbedVideoField
import random
import string


# Функционал стен пользователей

# Стены пользователей, использует абстрактный класс SiriusoBazaAbstrakta3
class MurojUzantoMuro(SiriusoBazaAbstrakta3):

    # владелец (пользователь)
    posedanto = models.OneToOneField(Uzanto, verbose_name=_('Posedanto'), blank=False, default=None,
                                     on_delete=models.CASCADE)

    # доступ к стене, кто может публиковать
    aliro = models.ForeignKey(UzantojAliro, verbose_name=_('Aliro'), blank=False, default=None,
                              on_delete=models.CASCADE)

    # разрешено ли комментировать записи на стене и кому разрешено
    komentado_aliro = models.ForeignKey(UzantojAliro, verbose_name=_('Komentada aliro'), blank=False, default=None,
                                        related_name='%(app_label)s_%(class)s_komentado_aliro',
                                        on_delete=models.CASCADE)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'muroj_uzantoj_muroj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Muro de uzanto')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Muroj de uzantoj')

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле posedanto этой модели
        return '{}'.format(self.posedanto)


# Записи пользователей, использует абстрактный класс SiriusoBazaAbstraktaUzanto
class MurojUzantoEnskribo(SiriusoBazaAbstraktaUzanto):

    # ID записи для вывода
    id = models.IntegerField(_('ID'), default=0)

    # стена на которой опубликовано
    muro = models.ForeignKey(MurojUzantoMuro, verbose_name=_('Muro'), blank=False, default=None,
                             on_delete=models.CASCADE)

    # оригинал телепортированной записи из сообществ
    originalo = models.ForeignKey('MuroEnskribo', verbose_name=_('Origanalo de enskribo'), blank=True, null=True,
                                  default=None, on_delete=models.CASCADE)

    # оригинал телепортированной записи со стены пользователя
    originalo_uzanto = models.ForeignKey('self', verbose_name=_('Origanalo de uzanta enskribo'), null=True,
                                         blank=True, default=None, on_delete=models.CASCADE)

    # текст, многоязычный в JSON формате
    teksto = models.JSONField(verbose_name=_('Teksto'), blank=True, null=False, default=default_lingvo,
                                encoder=CallableEncoder)

    # доступ к записи (видимость), кто видит
    aliro = models.ForeignKey(UzantojAliro, verbose_name=_('Aliro'), blank=False, default=None,
                              on_delete=models.CASCADE)

    # разрешено ли комментировать запись и кому разрешено
    komentado_aliro = models.ForeignKey(UzantojAliro, verbose_name=_('Komentada aliro'), blank=False, default=None,
                                        related_name='%(app_label)s_%(class)s_komentado_aliro',
                                        on_delete=models.CASCADE)

    # запись закреплена (да или нет)
    fiksa = models.BooleanField(_('Fiksa'), blank=False, default=False)

    # видео
    video = EmbedVideoField(verbose_name=_('Video'), blank=True, default='')

    # ссылка на ВК
    vk_referenco = models.TextField(_('VK referenco'), blank=True, default='')

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'muroj_uzantoj_enskriboj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Enskribo de uzanto')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Enskriboj de uzantoj')
        # права доступа
        permissions = (
            ('povas_vidi_uzantan_enskribon', _('Povas vidi uzantan enskribon')),
            ('povas_krei_uzantan_enskribon', _('Povas krei uzantan enskribon')),
            ('povas_forigi_uzantan_enskribon', _('Povas forigi uzantan enskribon')),
            ('povas_shanghi_uzantan_enskribon', _('Povas ŝanĝi uzantan enskribon')),
            ('povas_publikigi_uzantan_enskribon', _('Povas publikigi uzantan enskribon')),
            ('povas_arkivigi_uzantan_enskribon', _('Povas arkivigi uzantan enskribon')),
            ('povas_komenti_uzantan_enskribon', _('Povas komenti uzantan enskribon')),
            ('povas_interesighos_uzantan_enskribon', _('Povas interesiĝos uzantan enskribon')),
            ('povas_teletransponi_enskribon', _('Povas teletransponi uzantan enskribon'))
        )

    def _get_user_permissions(self, user_obj):
        perms = Permission.objects.none()

        if user_obj.is_authenticated:
            # Если пользователь - владелец стены
            if self.posedanto.id == user_obj.id:
                try:
                    for grupo in SpecialajGrupoj.objects.get(kodo='uzanta_pagho').grupoj.all():
                        perms |= grupo.permissions.filter(content_type__app_label='versioj')
                except SpecialajGrupoj.DoesNotExist:
                    pass

            # Парсим права зарегистрированных
            try:
                for grupo in SpecialajGrupoj.objects.get(kodo='registrita').grupoj.all():
                    perms |= grupo.permissions.filter(content_type__app_label='versioj')
            except SpecialajGrupoj.DoesNotExist:
                pass

        return perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.has_perm('muroj.povas_vidi_uzantan_enskribon'):
            cond = models.Q(forigo=False)

            if not user_obj.has_perm('muroj.povas_publikigi_uzantan_enskribon'):
                cond &= models.Q(publikigo=True)

            if not user_obj.has_perm('muroj.povas_arkivigi_uzantan_enskribon'):
                cond &= models.Q(arkivo=False)

            if user_obj.is_authenticated:
                # Если есть соответствующие права на странице пользователя
                if perms.has_user_page_perm('muroj.povas_arkivigi_uzantan_enskribon'):
                    cond |= models.Q(posedanto=user_obj, arkivo=True)

                if perms.has_user_page_perm('muroj.povas_publikigi_uzantan_enskribon'):
                    cond |= models.Q(posedanto=user_obj, publikigo=False)
        else:
            cond = models.Q(uuid__isnull=True)

        return cond

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле teksto этой модели
        return '{}'.format(get_enhavo(self.teksto, empty_values=True)[0])

    # абсолютный путь
    def get_absolute_url(self):
        return reverse('muroj:muro_uzanto_unu', args=[str(self.posedanto_id), str(self.id)])

    # реализация автоинкремента при сохранении
    def save(self, force_insert=False, force_update=False, using=None,
             update_fields=None):
        if self.id is None or not self.id:
            model = getattr(sys.modules[self.__module__], self.__class__.__name__)
            next_id = model.objects.filter(posedanto=self.posedanto).aggregate(Max('id'))['id__max']

            next_id = 1 if next_id is None else next_id + 1

            super(model, self).__setattr__('id', next_id)

        super(MurojUzantoEnskribo, self).save(force_insert=force_insert, force_update=force_update, using=using,
                                              update_fields=update_fields)


# Лайки записей пользователей, использует абстрактный класс SiriusoBazaAbstraktaUzanto
class MurojUzantoEnskriboInterese(SiriusoBazaAbstraktaUzanto):

    # владелец (запись общественного проекта)
    enskribo = models.ForeignKey(MurojUzantoEnskribo, verbose_name=_('Posedanto'), blank=False, default=None,
                                 on_delete=models.CASCADE)

    # запись интересна (да или нет)
    interese = models.BooleanField(_('Interese'), default=False)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'muroj_uzantoj_enskriboj_interese'
        # читабельное название модели, в единственном числе
        verbose_name = _('Interese (enskribo de uzanto)')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Interese (enskriboj de uzantoj)')

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле posedanto модели
        return '{}'.format(self.enskribo)


# Генерация случайного названия и переименование загружаемых картинок записей пользователей
def muroj_uzanto_enskribo_bildo_nomo(instance, filename):
    letters = string.ascii_letters + string.digits
    rnd_string = ''.join(random.choice(letters) for i in range(10))
    # указание папки для хранения файлов и собирание конечного названия с сохранением изначального расширения
    return 'uzantoj/enskriboj/bildoj/{0}.{1}'.format(rnd_string, filename.split('.')[-1])


# Изображения записей пользователей, использует абстрактный класс SiriusoBazaAbstraktaKomunumoj
class MurojUzantoEnskriboBildo(SiriusoBazaAbstraktaUzanto):

    # владелец (запись пользователей)
    posedanto = models.ForeignKey(MurojUzantoEnskribo, verbose_name=_('Posedanto'), blank=False, default=None,
                                  on_delete=models.CASCADE)

    # изображение для отображения (нужно сделать размер до 1280x1024 включительно)
    bildo = models.ImageField(_('Bildo'), upload_to=muroj_uzanto_enskribo_bildo_nomo, blank=False, default=None)

    # # миниатюра изображения
    # bildo_min = models.ImageField(_('Miniaturo'), blank=True, null=True)

    # # разрешено ли комментировать изображение и кому разрешено
    # komentado_aliro = models.ForeignKey(UzantojAliro, verbose_name=_('Komentada aliro'), blank=False, default=None,
    #                                     related_name='%(app_label)s_%(class)s_komentado_aliro',
    #                                     on_delete=models.CASCADE)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'muroj_uzantoj_enskriboj_bildoj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Bildo de enskribo de uzanto')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Bildoj de enskriboj de uzantoj')

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле posedanto модели
        return '{}'.format(self.posedanto)


# Комментарии записей пользователей, использует абстрактный класс SiriusoKomentoAbstrakta
class MurojUzantoEnskriboKomento(SiriusoKomentoAbstrakta):

    # ID записи для вывода
    id = models.IntegerField(_('ID'), default=0)

    # владелец (запись пользователей)
    posedanto = models.ForeignKey(MurojUzantoEnskribo, verbose_name=_('Posedanto'), blank=False, default=None,
                                  on_delete=models.CASCADE)

    # текст, многоязычный в JSON формате
    teksto = models.JSONField(verbose_name=_('Teksto'), blank=True, null=False, default=default_lingvo,
                                encoder=CallableEncoder)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'muroj_uzantoj_enskriboj_komentoj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Komento de enskribo de uzanto')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Komentoj de enskriboj de uzantoj')
        # права доступа
        permissions = (
            ('povas_vidi_uzantan_komenton', _('Povas vidi uzantan komenton')),
            ('povas_krei_uzantan_komenton', _('Povas krei uzantan komenton')),
            ('povas_forigi_uzantan_komenton', _('Povas forigi uzantan komenton')),
            ('povas_shanghi_uzantan_komenton', _('Povas ŝanĝi uzantan komenton')),
            ('povas_publikigi_uzantan_komenton', _('Povas publikigi uzantan komenton')),
        )

    def _get_user_permissions(self, user_obj):
        return Permission.objects.none()

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.has_perm('muroj.povas_vidi_uzantan_komenton'):
            cond = models.Q(forigo=False)

            if not user_obj.has_perm('muroj.povas_publikigi_uzantan_komenton'):
                subcond = (
                    models.Q(publikigo=True) if user_obj.is_anonymous
                    else models.Q(publikigo=False, autoro=user_obj)
                )
                cond &= models.Q(subcond)
        else:
            cond = models.Q(uuid__isnull=True)

        return cond

    # реализация автоинкремента при сохранении
    def save(self, force_insert=False, force_update=False, using=None,
             update_fields=None):
        if self.id is None or not self.id:
            model = getattr(sys.modules[self.__module__], self.__class__.__name__)
            next_id = model.objects.filter(posedanto__muro=self.posedanto.muro).aggregate(Max('id'))['id__max']

            if next_id is None:
                next_id = 1
            else:
                next_id = next_id + 1
            super(model, self).__setattr__('id', next_id)

        super(MurojUzantoEnskriboKomento, self).save(force_insert=force_insert, force_update=force_update, using=using,
                                                     update_fields=update_fields)


# Функционал стен сообществ
# Абстрактный класс стен сообществ, использует абстрактный класс SiriusoBazaAbstrakta3
class MurojMuroAbstrakta(SiriusoBazaAbstrakta3):

    # доступ к стене, кто может публиковать
    aliro = models.ForeignKey(KomunumojAliro, verbose_name=_('Aliro'), blank=False, default=None,
                              related_name='%(app_label)s_%(class)s_aliro', on_delete=models.CASCADE)

    # разрешено ли комментировать записи на стене и кому разрешено
    komentado_aliro = models.ForeignKey(KomunumojAliro, verbose_name=_('Komentada aliro'), blank=False, default=None,
                                        related_name='%(app_label)s_%(class)s_komentado_aliro',
                                        on_delete=models.CASCADE)

    # дополнительные настройки для модели
    class Meta:
        # указание что это абстрактный класс
        abstract = True
        # читабельное название модели, в единственном числе
        verbose_name = _('Muro')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Muroj')

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле posedanto модели
        return '{}'.format(self.posedanto)


# Абстрактный класс записей сообществ, использует абстрактный класс SiriusoBazaAbstraktaKomunumoj
class MurojEnskriboAbstrakta(SiriusoBazaAbstraktaKomunumoj):

    # показать автора (да или нет)
    autoro_montri = models.BooleanField(_('Montru aŭtoro'), blank=False, default=False)

    # доступ к записи (видимость), кто видит
    aliro = models.ForeignKey(KomunumojAliro, verbose_name=_('Aliro'), blank=False, default=None,
                              related_name='%(app_label)s_%(class)s_aliro', on_delete=models.CASCADE)

    # разрешено ли комментировать запись и кому разрешено
    komentado_aliro = models.ForeignKey(KomunumojAliro, verbose_name=_('Komentada aliro'), blank=False, default=None,
                                        related_name='%(app_label)s_%(class)s_komentado_aliro',
                                        on_delete=models.CASCADE)

    # видео
    video = EmbedVideoField(verbose_name=_('Video'), blank=True, default='')

    # ссылка на ВК
    vk_referenco = models.TextField(_('VK referenco'), blank=True, default='')

    # дополнительные настройки для модели
    class Meta:
        # указание что это абстрактный класс
        abstract = True
        # читабельное название модели, в единственном числе
        verbose_name = _('Enskribo')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Enskriboj')

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле teksto модели
        return '{}'.format(get_enhavo(self.teksto, empty_values=True)[0])


######################################
class Muro(MurojMuroAbstrakta):

    # владелец (совет)
    posedanto = models.OneToOneField(Komunumo, verbose_name=_('Posedanto'), blank=False, default=None,
                                     on_delete=models.CASCADE)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'muroj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Muro de komunumoj')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Muroj de komunumoj')


# Записи стен
class MuroEnskribo(MurojEnskriboAbstrakta):

    # ID записи для вывода
    id = models.IntegerField(_('ID'), default=0)

    # владелец (сообщество)
    posedanto = models.ForeignKey(Komunumo, verbose_name=_('Posedanto'), blank=False, default=None,
                                  on_delete=models.CASCADE)

    # оригинал телепортированной записи из сообществ
    originalo = models.ForeignKey('self', verbose_name=_('Origanalo de enskribo'), blank=True, default=None,
                                  null=True, on_delete=models.CASCADE)

    # оригинал телепортированной записи со стены пользователя
    originalo_uzanto = models.ForeignKey(MurojUzantoEnskribo, verbose_name=_('Origanalo de uzanta enskribo'),
                                         null=True, blank=True, default=None, on_delete=models.CASCADE)

    # стена
    muro = models.ForeignKey(Muro, verbose_name=_('Muro'), blank=False, default=None,
                             on_delete=models.CASCADE)

    # текст, многоязычный в JSON формате
    teksto = models.JSONField(verbose_name=_('Teksto'), blank=True, null=False, default=default_lingvo,
                                encoder=CallableEncoder)

    # запись закреплена (да или нет)
    fiksa = models.BooleanField(_('Fiksa'), blank=False, default=False)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'muroj_enskriboj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Enskribo de komunumo')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Enskriboj de komunumoj')
        # права доступа
        permissions = (
            ('povas_vidi_enskribon', _('Povas vidi enskribon')),
            ('povas_krei_enskribon', _('Povas krei enskribon')),
            ('povas_forigi_enskribon', _('Povas forigi enskribon')),
            ('povas_shanghi_enskribon', _('Povas ŝanĝi enskribon')),
            ('povas_publikigi_enskribon', _('Povas publikigi enskribon')),
            ('povas_arkivigi_enskribon', _('Povas arkivigi enskribon')),
            ('povas_komenti_enskribon', _('Povas komenti enskribon')),
            ('povas_interesighos_enskribon', _('Povas interesiĝos enskribon')),
            ('povas_teletransponi_enskribon', _('Povas teletransponi enskribon'))
        )

    def _get_user_permissions(self, user_obj):
        perms = Permission.objects.none()

        if user_obj.is_authenticated:
            # Если пользователь - админ или модератор сообщества
            try:
                membro = KomunumoMembro.objects.select_related('tipo').get(
                    posedanto=self.posedanto, autoro=user_obj, forigo=False
                )

                if membro.tipo.kodo in ('administranto', 'komunumano-adm'):
                    grupoj = SpecialajGrupoj.objects.get(kodo='komunumano-adm').grupoj.all()
                elif membro.tipo.kodo in ('moderiganto', 'komunumano-mod'):
                    grupoj = SpecialajGrupoj.objects.get(kodo='kom_moderiganto').grupoj.all()
                else:
                    grupoj = SpecialajGrupoj.objects.none()

                if grupoj:
                    for grupo in grupoj:
                        perms |= grupo.permissions.filter(content_type__app_label='versioj')
            except (KomunumoMembro.DoesNotExist, SpecialajGrupoj.DoesNotExist):
                pass

            # Парсим права зарегистрированных
            try:
                for grupo in SpecialajGrupoj.objects.get(kodo='registrita').grupoj.all():
                    perms |= grupo.permissions.filter(content_type__app_label='versioj')
            except SpecialajGrupoj.DoesNotExist:
                pass

        return perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.has_perm('muroj.povas_vidi_enskribon'):
            cond = models.Q(forigo=False)

            if not user_obj.has_perm('muroj.povas_publikigi_enskribon'):
                cond &= models.Q(publikigo=True)

            if not user_obj.has_perm('muroj.povas_arkivigi_enskribon'):
                cond &= models.Q(arkivo=False)

            if user_obj.is_authenticated:
                # Если есть права у админа или модера на просмотр архивных
                if (perms.has_komunumo_adm_perms('muroj.povas_arkivigi_enskribon')
                    or perms.has_komunumo_mod_perms('muroj.povas_arkivigi_enskribon')
                ):
                    cond |= models.Q(
                        posedanto__komunumoj_komunumomembro_posedanto__tipo__kodo__in=[
                            'komunumano-adm', 'administranto', 'komunumano-mod', 'moderiganto'
                        ], posedanto__komunumoj_komunumomembro_posedanto__autoro=user_obj,
                        posedanto__komunumoj_komunumomembro_posedanto__forigo=False,
                        arkivo=True)

                # Если есть права у админа или модера на просмотр черновиков
                if (perms.has_komunumo_adm_perms('muroj.povas_publikigi_enskribon')
                    or perms.has_komunumo_mod_perms('muroj.povas_publikigi_enskribon')
                ):
                    cond |= models.Q(
                        posedanto__komunumoj_komunumomembro_posedanto__tipo__kodo__in=[
                            'komunumano-adm', 'administranto', 'komunumano-mod', 'moderiganto'
                        ], posedanto__komunumoj_komunumomembro_posedanto__autoro=user_obj,
                        posedanto__komunumoj_komunumomembro_posedanto__forigo=False,
                        publikigo=False
                    )
        else:
            cond = models.Q(uuid__isnull=True)

        return cond

    # реализация автоинкремента при сохранении
    def save(self, force_insert=False, force_update=False, using=None,
             update_fields=None):
        if self.id is None or not self.id:
            model = getattr(sys.modules[self.__module__], self.__class__.__name__)
            next_id = model.objects.filter(posedanto=self.posedanto).aggregate(Max('id'))['id__max']

            if next_id is None:
                next_id = 1
            else:
                next_id = next_id + 1
            super(model, self).__setattr__('id', next_id)

        super(MuroEnskribo, self).save(force_insert=force_insert, force_update=force_update, using=using,
                                        update_fields=update_fields)


# Лайки записей советов, использует абстрактный класс SiriusoBazaAbstraktaKomunumoj
class MuroEnskriboInterese(SiriusoBazaAbstraktaKomunumoj):

    # владелец (запись общественного проекта)
    enskribo = models.ForeignKey(MuroEnskribo, verbose_name=_('Posedanto'), blank=False, default=None,
                                 on_delete=models.CASCADE)

    # запись интересна (да или нет)
    interese = models.BooleanField(_('Interese'), default=False)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'muroj_enskriboj_interese'
        # читабельное название модели, в единственном числе
        verbose_name = _('Interese (enskribo de komunumo)')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Interese (enskriboj de komunumoj)')

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле posedanto модели
        return '{}'.format(self.enskribo)


# Генерация случайного названия и переименование загружаемых картинок записей советов
def muroj_enskribo_bildo_nomo(instance, filename):
    letters = string.ascii_letters + string.digits
    rnd_string = ''.join(random.choice(letters) for i in range(10))
    # указание папки для хранения файлов и собирание конечного названия с сохранением изначального расширения
    return 'komunumoj/enskriboj/bildoj/{0}.{1}'.format(rnd_string, filename.split('.')[-1])


# Изображения записей советов, использует абстрактный класс SiriusoBazaAbstraktaKomunumoj
class MuroEnskriboBildo(SiriusoBazaAbstraktaKomunumoj):

    # владелец
    posedanto = models.ForeignKey(MuroEnskribo, verbose_name=_('Posedanto'), blank=False, default=None,
                                  on_delete=models.CASCADE)

    # изображение для отображения (нужно сделать размер до 1280x1024 включительно)
    bildo = models.ImageField(_('Bildo'), upload_to=muroj_enskribo_bildo_nomo, blank=False, default=None)

    # # миниатюра изображения
    # bildo_min = models.ImageField(_('Miniaturo'), blank=True, null=True)

    # # разрешено ли комментировать изображение и кому разрешено
    # komentado_aliro = models.ForeignKey(KomunumojAliro, verbose_name=_('Komentada aliro'), blank=False, default=None,
    #                                     related_name='%(app_label)s_%(class)s_komentado_aliro',
    #                                     on_delete=models.CASCADE)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'muroj_enskriboj_bildoj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Bildo de enskribo de komunumo')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Bildoj de enskriboj de komunumoj')

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле posedanto модели
        return '{}'.format(self.posedanto)


# Комментарии записей, использует абстрактный класс SiriusoKomentoAbstrakta
class MuroEnskriboKomento(SiriusoKomentoAbstrakta):

    # ID записи для вывода
    id = models.IntegerField(_('ID'), default=0)

    # владелец (запись совета)
    posedanto = models.ForeignKey(MuroEnskribo, verbose_name=_('Posedanto'), blank=False, default=None,
                                  on_delete=models.CASCADE)

    # текст, многоязычный в JSON формате
    teksto = models.JSONField(verbose_name=_('Teksto'), blank=True, null=False, default=default_lingvo,
                                encoder=CallableEncoder)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'muroj_enskriboj_komentoj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Komento de enskribo de komunumo')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Komentoj de enskriboj de komunumoj')
        # права доступа
        permissions = (
            ('povas_vidi_komenton', _('Povas vidi komenton')),
            ('povas_krei_komenton', _('Povas krei komenton')),
            ('povas_forigi_komenton', _('Povas forigi komenton')),
            ('povas_shanghi_komenton', _('Povas ŝanĝi komenton')),
            ('povas_publikigi_komenton', _('Povas publikigi komenton')),
        )

    def _get_user_permissions(self, user_obj):
        return Permission.objects.none()

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.has_perm('muroj.povas_vidi_komenton'):
            cond = models.Q(forigo=False)

            if not user_obj.has_perm('muroj.povas_publikigi_komenton'):
                subcond = (
                    models.Q(publikigo=True) if user_obj.is_anonymous
                    else models.Q(publikigo=False, autoro=user_obj)
                )
                cond &= models.Q(subcond)
        else:
            cond = models.Q(uuid__isnull=True)

        return cond

    # реализация автоинкремента при сохранении
    def save(self, force_insert=False, force_update=False, using=None,
             update_fields=None):
        if self.id is None or not self.id:
            model = getattr(sys.modules[self.__module__], self.__class__.__name__)
            next_id = model.objects.filter(posedanto__muro=self.posedanto.muro).aggregate(Max('id'))['id__max']

            if next_id is None:
                next_id = 1
            else:
                next_id = next_id + 1
            super(model, self).__setattr__('id', next_id)

        super(MuroEnskriboKomento, self).save(force_insert=force_insert, force_update=force_update, using=using,
                                                     update_fields=update_fields)
######################################
# Генерация случайного названия и переименование загружаемых картинок записей советов
def muroj_soveto_enskribo_bildo_nomo(instance, filename):
    letters = string.ascii_letters + string.digits
    rnd_string = ''.join(random.choice(letters) for i in range(10))
    # указание папки для хранения файлов и собирание конечного названия с сохранением изначального расширения
    return 'sovetoj/enskriboj/bildoj/{0}.{1}'.format(rnd_string, filename.split('.')[-1])


# Генерация случайного названия и переименование загружаемых картинок записей групп
def muroj_grupo_enskribo_bildo_nomo(instance, filename):
    letters = string.ascii_letters + string.digits
    rnd_string = ''.join(random.choice(letters) for i in range(10))
    # указание папки для хранения файлов и собирание конечного названия с сохранением изначального расширения
    return 'grupoj/enskriboj/bildoj/{0}.{1}'.format(rnd_string, filename.split('.')[-1])


# Генерация случайного названия и переименование загружаемых картинок записей организаций
def muroj_organizo_enskribo_bildo_nomo(instance, filename):
    letters = string.ascii_letters + string.digits
    rnd_string = ''.join(random.choice(letters) for i in range(10))
    # указание папки для хранения файлов и собирание конечного названия с сохранением изначального расширения
    return 'organizoj/enskriboj/bildoj/{0}.{1}'.format(rnd_string, filename.split('.')[-1])


# Генерация случайного названия и переименование загружаемых картинок записей общественных проектов
def muroj_sociaprojekto_enskribo_bildo_nomo(instance, filename):
    letters = string.ascii_letters + string.digits
    rnd_string = ''.join(random.choice(letters) for i in range(10))
    # указание папки для хранения файлов и собирание конечного названия с сохранением изначального расширения
    return 'sociaprojektoj/enskriboj/bildoj/{0}.{1}'.format(rnd_string, filename.split('.')[-1])
